/* 
 * Copyright 2011 kOSMik.
 * This file is part of kOSMik.
 * 
 * kOSMik is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * kOSMik is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with kOSMik.  If not, see <http://www.gnu.org/licenses/>.
 *  
 * kOSMik:
 * Open Street Map - Editor.
 * http://code.google.com/p/swp-dv-ws2010-osm-2/
 */

package de.fuberlin.kosmik.gui.activity;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ImageButton;
import android.widget.ListView;
import de.fuberlin.kosmik.R;
import de.fuberlin.kosmik.data.osmt.OsmtNodeRecord;
import de.fuberlin.kosmik.gui.view.adapter.TagListAdapter;

/**
 * 
 * the TagPickerActivity shows the user a categorized list to select a bundle of
 * tags.
 * 
 * at least, this activity calls the TagBundleActivity. If the user confirmed
 * his choices he makes in TagBundleActivity, the TagPickerActivity returns the
 * result to the calling ViewActivity
 * 
 * @author Johannes
 * @see TagListAdapter
 * @see ViewActivity#letUserPickAPoi()
 * @see ViewActivity#letUserStartWayTracking()
 * @see ViewActivity#letUserStartAreaTracking()
 * @see TagBundleActivity
 * @see TagEditingActivity
 * 
 */
public class TagPickerActivity extends Activity {

	private static final int INTENT_TAG_PICKER = 1;
	private static final int INTENT_TAG_BUNDLE = 2;
	private static final int INTENT_TAG_ADD_DIRECTLY = 3;
	private static final int RESULT_USER_CANCELED = RESULT_FIRST_USER;

	/**
	 * Default values for the title, in case a null as name is given.
	 */
	String title = "TagPicker";
	/**
	 * The id of the node, which is parent to all shown osmStructureNodes.
	 */
	int osmtParentNodeId = 0;

	/**
	 * Differ tags between ways, nodes etc.
	 */
	private int osmtElementFilter;

	private ListView lstTagPickerListView;

	private ImageButton btnSearch;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.tagpicker);

		processParams();

		initViews();

	}

	/**
	 * Get extras and set attributes.
	 */
	private void processParams() {
		// extract params
		final Bundle extras = getIntent().getExtras();

		// get names for the list items
		osmtParentNodeId = extras.getInt("OSM_PARENT_NODE_ID");

		// get element filter
		osmtElementFilter = extras.getInt("OSM_ELEMENT_FILTER");

		// get list title
		final String offeredTitle = extras.getString("TITLE");
		if (offeredTitle != null)
			this.title = offeredTitle;
	}

	private void initViews() {
		if (title == null) // set default value if empty
			title = "TagPicker";

		lstTagPickerListView = (ListView) findViewById(R.id.tagpicker_tagList);
		// handle item design by adapter
		lstTagPickerListView.setAdapter(new TagListAdapter(this, osmtParentNodeId,
				osmtElementFilter));
		// react on click events
		lstTagPickerListView.setOnItemClickListener(getTagPickerListOnItemClickListener());
		// react on touch event
		lstTagPickerListView.setOnTouchListener(getTagPickerListGestureListener());
		btnSearch = (ImageButton) findViewById(R.id.action_bar_search_button);
		btnSearch.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {

				Intent intent = new Intent(TagPickerActivity.this, TagSearchActivity.class);
				// TODO use real filters
				intent.putExtra(TagSearchActivity.KEY_TABLE_FILTER,
						TagSearchActivity.TABLE_FILTER_ALL);
				intent.putExtra(TagSearchActivity.KEY_ELEMENT_FILTER, osmtElementFilter);
				startActivityForResult(intent, INTENT_TAG_BUNDLE);

			}
		});
	}

	private OnTouchListener getTagPickerListGestureListener() {

		class MyGestureDetector extends SimpleOnGestureListener {
			private static final int MIN_SWIPE_DISTANCE = 120;
			private static final int MAX_SWIPE_Y_DRIFT = 250;
			private static final int SWIPE_THRESHOLD_VELOCITY = 200;

			@Override
			public boolean onFling(MotionEvent motionEvent1, MotionEvent motionEvent2,
					float velocityX, float velocityY) {
				// if drift in y range to long, skip
				if (Math.abs(motionEvent1.getY() - motionEvent2.getY()) > MAX_SWIPE_Y_DRIFT)
					return false;

				final float absVelocityX = Math.abs(velocityX);
				// swipe right to left ?
				if (motionEvent1.getX() - motionEvent2.getX() > MIN_SWIPE_DISTANCE
						&& absVelocityX > SWIPE_THRESHOLD_VELOCITY) {
					onLeftSwipe();
				} else
				// swipe left to right ?
				if (motionEvent2.getX() - motionEvent1.getX() > MIN_SWIPE_DISTANCE
						&& absVelocityX > SWIPE_THRESHOLD_VELOCITY) {
					onRightSwipe();
				}

				return false;
			}

		}

		final GestureDetector gestureDetector = new GestureDetector(new MyGestureDetector());

		return new View.OnTouchListener() {
			@Override
			public boolean onTouch(View v, MotionEvent event) {
				return gestureDetector.onTouchEvent(event);
			}
		};
	}

	/**
	 * Process a left swipe.
	 * 
	 * when a left swipe occur, we finish this activity and return a cancel
	 * result
	 */
	void onLeftSwipe() {
		addTagDirectly();
	}

	/**
	 * Process a right swipe.
	 */
	void onRightSwipe() {
		returnToPreviewActivity(RESULT_CANCELED, new Intent());
	}

	private OnItemClickListener getTagPickerListOnItemClickListener() {

		return new OnItemClickListener() {

			@Override
			public void onItemClick(AdapterView<?> l, View v, int position, long id) {
				// get the text of selected item
				final OsmtNodeRecord clickedItemNode = ((TagListAdapter.ListItem) v.getTag()).osmtNodeRecord;

				// TODO : Test OsmtNode.useOneMoreTime
				//
				// try { // update statistic for the node
				// final OsmtNode clickedNode = new OsmtNode(
				// OsmtDataFactory.createOsmtData(TagPickerActivity.this),
				// clickedItemNode);
				// OsmtNode.useOneMoreTime(clickedNode);
				// } catch (OsmtObjectException e) {
				// Log.w(Constants.TAG, "Cannot update statistic for a node");
				// }

				if (!clickedItemNode.isBundle) {
					// if this object is likewise a theme, call this
					// list-activity recursively
					final Intent childNodeIntent = new Intent(TagPickerActivity.this,
							TagPickerActivity.class);
					childNodeIntent.putExtra("TITLE", title);
					childNodeIntent.putExtra("OSM_ELEMENT_FILTER", osmtElementFilter);
					childNodeIntent.putExtra("OSM_PARENT_NODE_ID", clickedItemNode.id);
					startActivityForResult(childNodeIntent, INTENT_TAG_PICKER);
				} else {
					// otherwise is must be a OsmBundle. Therefore we call an
					// instance of TagBundleActivity
					final Intent childNodeIntent = new Intent(TagPickerActivity.this,
							TagBundleActivity.class);
					childNodeIntent.putExtra("OSM_BUNDLE_ID", clickedItemNode.id);
					startActivityForResult(childNodeIntent, INTENT_TAG_BUNDLE);
				}

			}

		};

	}

	/**
	 * Starts TagEditingActivity to enter a Key Value pair.
	 */
	private void addTagDirectly() {
		Intent tagEditingIntent = new Intent(TagPickerActivity.this, TagEditingActivity.class);
		// set parameters
		tagEditingIntent.putExtra("KEY", "");
		tagEditingIntent.putExtra("VALUE", "");
		// start TagEditingActivity
		startActivityForResult(tagEditingIntent, INTENT_TAG_ADD_DIRECTLY);
	}

	/**
	 * Call this method to quit this activity by returning a data bundle.
	 * 
	 * @param resultCode that the calling activity receives when finishing
	 * @param resultIntent that contain the return data
	 */
	private void returnToPreviewActivity(int resultCode, Intent resultIntent) {
		// pass the result to call
		setResult(resultCode, resultIntent);
		// and return to super activity
		finish();
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);
		if (resultCode == RESULT_OK) {
			switch (requestCode) {
			case INTENT_TAG_ADD_DIRECTLY:
				final Bundle returnedBundle = data.getExtras();
				final Bundle resultBundle = new Bundle();
				final String newKeyName = returnedBundle.getString("KEY");
				final String newValueName = returnedBundle.getString("VALUE");
				if (newKeyName != null && newKeyName.length() > 0 && newValueName != null
						&& newValueName.length() > 0)
					resultBundle.putString(newKeyName, newValueName);

				final Intent resultIntent = new Intent();
				resultIntent.putExtra("BUNDLE_NAME",
						getString(R.string.tagpicker__internal_free_input_tag_name));
				resultIntent.putExtra("KEY_VALUE_BUNDLE", resultBundle);
				// set result values and return to super activity
				returnToPreviewActivity(RESULT_OK, resultIntent);
				break;
			default: // pass results
				returnToPreviewActivity(RESULT_OK, data);
				break;
			}
		} else if (resultCode == RESULT_USER_CANCELED) {
			returnToPreviewActivity(RESULT_USER_CANCELED, new Intent());
		} else {
			switch (requestCode) {
			case INTENT_TAG_BUNDLE:
				returnToPreviewActivity(RESULT_USER_CANCELED, new Intent());
				break;
			default: // INTENT_TAG_PICKER
				// nothing
				break;
			}
		}
	}

}
